package com.skeeey.aim.service.impl;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.skeeey.aim.model.AutoRecord;
import com.skeeey.aim.model.AutoStatus;
import com.skeeey.aim.model.Dealer;
import com.skeeey.aim.model.Workload;
import com.skeeey.aim.model.statistics.StatisticRecord;
import com.skeeey.aim.service.RecordService;
import com.skeeey.aim.service.dao.AutoRecordDao;
import com.skeeey.aim.service.dao.DaoException;
import com.skeeey.aim.service.dao.DealerDao;
import com.skeeey.aim.service.dao.WorkloadDao;
import com.skeeey.aim.util.AIMUtil;
import com.skeeey.aim.util.Dealers;
import com.skeeey.aim.util.RS;

public class RecordServiceImpl implements RecordService {
	
	private AutoRecordDao autoRecordDao;
	
	private DealerDao dealerDao;
	
	private WorkloadDao workloadDao;

	public void setAutoRecordDao(AutoRecordDao autoRecordDao) {
		this.autoRecordDao = autoRecordDao;
	}
	
	public void setDealerDao(DealerDao dealerDao) {
		this.dealerDao = dealerDao;
	}
	
	public void setWorkloadDao(WorkloadDao workloadDao) {
		this.workloadDao = workloadDao;
	}

	@Override
	public void saveOriginalRecords(List<AutoRecord> records) {
		autoRecordDao.saveAutoRecords(records);
	}

	@Override
	public List<AutoRecord> getAutoRecordsBy(int status, String timeStamp, String dealerCode) {
		return autoRecordDao.getRecordsBy(status, timeStamp, dealerCode);
	}

	@Override
	public void deletOriginalRecordBy(String recordId) {
		try {
			autoRecordDao.deleteByKey(recordId);
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void updateOriginalRecord(AutoRecord record) {
		try {
			autoRecordDao.update(record);
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean isValidDealer(String dealerCode) {
		List<Dealer> dealers = dealerDao.findDealersBy(dealerCode);
		return dealers.size() == 1;
	}

	@Override
	public AutoRecord findAutoRecordBy(String dealerCode, String vinCode) {
		AutoRecord autoRecord = null;
		List<AutoRecord> records = autoRecordDao.findRecordBy(dealerCode, vinCode);
		if(records.size() > 0) {
			autoRecord = records.get(0);
		}
		return autoRecord;
	}

	@Override
	public Dealer findDealerBy(String dealerCode) {
		Dealer dealer = null;
		List<Dealer> dealers = dealerDao.findDealersBy(dealerCode);
		if(dealers.size() > 0) {
			dealer = dealers.get(0);
		}
		return dealer;
	}

//	@Override
//	public List<AutoRecord> getAutoRecordsBy(List<String> vinCodes) {
//		List<AutoRecord> records = new ArrayList<AutoRecord>();
//		for(String vinCode : vinCodes) {
//			AutoRecord record = findAutoRecordBy(vinCode);
//			if(record != null) {
//				if(record.getOrderStartDate() != null && record.getOrderStartDate().length() != 0) {
//					try {
//						Date dd1 = new SimpleDateFormat("yyyyMMdd").parse(record.getOrderStartDate());
//						Date dd2 = new Date();
//						record.setActualAge((int)((dd2.getTime() - dd1.getTime())/ 24 / 3600000));
//					} catch (ParseException e) {
//						//logger.warn("calculate actual auto age failed [" + record.getOrderStartDate() + "]");
//					}
//				}
//				
//				if(record.getAutoCode() != null) {
//					record.setAutoKind(RS.getInst().getAutoKindBy(record.getAutoCode()));
//				}
//				
//				if(record.getStorageLocation() == null) {
//					record.setStorageLocation(record.getStorageLocationCode());
//				}
//				records.add(record);
//			}
//		}
//		return records;
//	}

	@Override
	public StatisticRecord createStatisticRecordBy(Dealer dealer, String timeStamp) {
		StatisticRecord sr = new StatisticRecord(dealer);
		for(int i = 0; i < 7; i++) {
			sr.putRecords(i, getStatisticRecordsBy(i, dealer, timeStamp));
		}
		return sr;
	}
	
	private List<AutoRecord> updateRecode(List<AutoRecord> records, int index, String dataStroragePath, String location) {
		for(AutoRecord r : records) {
			if(r != null) {
				if(r.getOrderStartDate() != null && r.getOrderStartDate().length() != 0) {
					try {
						Date dd1 = new SimpleDateFormat("yyyyMMdd").parse(r.getOrderStartDate());
						Date dd2 = new Date();
						r.setActualAge((int)((dd2.getTime() - dd1.getTime())/ 24 / 3600000));
					} catch (ParseException e) {
						//logger.warn("calculate actual auto age failed (" + r.getOrderStartDate() + ")");
					}
				}
				
				if(r.getAutoCode() != null) {
					r.setAutoKind(RS.getInst().getAutoKindBy(r.getAutoCode()));
				}
				
				if(r.getStorageLocation() == null || r.getStorageLocation().length() == 0) {
					r.setStorageLocation(r.getStorageLocationCode());
				}
				
				if(index == 0) {
					try {
						String secondaryName = AIMUtil.getSecondaryNameBy(index, dataStroragePath, r.getVINCode());
						if(secondaryName != null) {
							r.setStorageLocation(secondaryName);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				if(index == 2) {
					try {
						String secondaryName = AIMUtil.getSecondaryNameBy(index, dataStroragePath, r.getVINCode());
						if(secondaryName != null) {
							r.setStorageLocation(secondaryName);
						} else {
							r.setStorageLocation(location);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		return records;
	}
	
	private List<AutoRecord> removeRecordsByVINCode(List<String> vinCodes, List<AutoRecord> records) {
		List<AutoRecord> removedRecords = new ArrayList<AutoRecord>();
		for(String vinCode : vinCodes) {
			for(AutoRecord record : records) {
				if(record.getVINCode().endsWith(vinCode)) {
					removedRecords.add(record);
					break;
				}
			}
		}
		for(AutoRecord record : removedRecords) {
			records.remove(record);
		}
		return records;
	}
	
	private List<AutoRecord> getRecordsByVINCode(List<String> vinCodes, List<AutoRecord> records) {
		List<AutoRecord> removedRecords = new ArrayList<AutoRecord>();
		for(String vinCode : vinCodes) {
			for(AutoRecord record : records) {
				if(record.getVINCode().endsWith(vinCode)) {
					removedRecords.add(record);
					break;
				}
			}
		}
		return removedRecords;
	}

	@Override
	public void updateOriginalRecords(List<AutoRecord> records, String timeStamp) {
		try {
			for(AutoRecord newAutoRecord: records) {
				String vinCode = newAutoRecord.getVINCode();
				if(vinCode != null && vinCode.length() != 0) {
					AutoRecord oldAutoRecord = findRecordBy(vinCode, timeStamp);
					if(oldAutoRecord == null) {
						autoRecordDao.save(newAutoRecord);
					} else {
						if(oldAutoRecord.update(newAutoRecord)) {
							autoRecordDao.update(oldAutoRecord);
						}
					}
				}
			}
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}
	
	private AutoRecord findRecordBy(String vinCode, String timeStamp) {
		AutoRecord autoRecord = null;
		List<AutoRecord> records = autoRecordDao.getRecordsBy(vinCode, timeStamp);
		if(records.size() > 0) {
			autoRecord = records.get(0);
		}
		return autoRecord;
	}

	@Override
	public List<AutoRecord> getStatisticRecordsBy(int index, Dealer dealer, String timeStamp) {
		List<AutoRecord> records = new ArrayList<AutoRecord>();
		String dataStroragePath = AIMUtil.findDataStoragePathStrBy(dealer, timeStamp);
		try {
			switch(index) {
			case 0:
				//0:状态一(在库 + VIN截图)
				List<String> vinCodes = AIMUtil.getVINCodesBy(0, dataStroragePath);
				List<AutoRecord> allRecords = updateRecode(autoRecordDao.getRecordsBy(AutoStatus.IN_INVENTORY.getVal(), timeStamp, dealer.getNetCode()), 0, dataStroragePath, null);
				records = getRecordsByVINCode(vinCodes, allRecords);
				break;
			case 1:
				//1:状态二(在库，除了状态一)
				vinCodes = AIMUtil.getVINCodesBy(0, dataStroragePath);
				allRecords = updateRecode(autoRecordDao.getRecordsBy(AutoStatus.IN_INVENTORY.getVal(), timeStamp, dealer.getNetCode()), -1, dataStroragePath, null);
				records = removeRecordsByVINCode(vinCodes, allRecords);
				break;
			case 2:
				//2:状态三
				List<AutoRecord> autoRecords = autoRecordDao.getRecordsBy(AutoStatus.IN_INVENTORY.getVal(), timeStamp, dealer.getNetCode());
				String location = null;
				if(!autoRecords.isEmpty()) {
					location = autoRecords.get(0).getStorageLocation();
					if(location == null || location.length() == 0) {
						location = autoRecords.get(0).getStorageLocationCode();
					}
				}
				List<AutoRecord> vRecords = updateRecode(autoRecordDao.getRecordsBy(AutoStatus.VIRTUAL.getVal(), timeStamp, dealer.getNetCode()), 2, dataStroragePath, location);
				vinCodes = AIMUtil.getVINCodesBy(2, dataStroragePath);
				records = getRecordsByVINCode(vinCodes, vRecords);
				break;
			case 4:
				//4:在途
				records = updateRecode(autoRecordDao.getRecordsBy(AutoStatus.ON_THE_WAY.getVal(), timeStamp, dealer.getNetCode()), -1, dataStroragePath, null);
				break;
			case 5:
				//5:未提
				records = updateRecode(autoRecordDao.getRecordsBy(AutoStatus.UNPICK_UP.getVal(), timeStamp, dealer.getNetCode()), -1, dataStroragePath, null);
				break;
			case 6:
				//6:虚拟未查到
				vRecords = updateRecode(autoRecordDao.getRecordsBy(AutoStatus.VIRTUAL.getVal(), timeStamp, dealer.getNetCode()), -1, dataStroragePath, null);
				vinCodes = AIMUtil.getVINCodesBy(2, dataStroragePath);
				records = removeRecordsByVINCode(vinCodes, vRecords);
				break;
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return records;
	}

	@Override
	public List<Dealer> getAllDealers() {
		return dealerDao.list();
	}

	@Override
	public List<Workload> getWorkloads(String userName, String year, String quarter) {
		return workloadDao.getWorkloadsBy(year, quarter, userName);
	}

	@Override
	public Map<String, Integer> getWorkloads(String year, String quarter) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		List<Workload> list = workloadDao.getWorkloadsBy(year, quarter);
		int count = 0;
		for(Workload wl : list) {
			if(map.containsKey(wl.getUserName())) {
				count = count + 1;
				map.put(wl.getUserName(), count);
			} else {
				count = 1;
				map.put(wl.getUserName(), count);
			}
		}
		return map;
	}

	@Override
	public void saveWorkload(Workload workload) {
		try {
			if(workloadDao.findWorkloadBy(workload.getUserName(), workload.getDealerName(), workload.getFinishDate()) == null) {
				workloadDao.save(workload);
			}
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void deletOriginalRecords(String dealerCode, String timeStamp) {
		autoRecordDao.deleteAutoRecords(dealerCode, timeStamp);
	}

	@Override
	public void deletWorkload(String dealerName, String finishDate) {
		workloadDao.deleteWorkloadBy(dealerName, finishDate);
	}

	@Override
	public void saveDealers() {
		dealerDao.saveDealers(Dealers.getDealers());
	}
	
	@Override
	public void saveDealersFromFile() {
		List<Dealer> dealers =  AIMUtil.getDealersFrom(new File("/mnt/auto_inventory_management/document/dealers.xls"));
		dealerDao.saveDealers(dealers);
	}
}